2015-10-16 81 views
1

這是我的第一個Angular指令。在指令鏈接中替換角度元素html

我想根據用於查找該內容的搜索條件對html內容進行簡單高亮處理。

問題是,這是工作的第一屆,但不是更多。我希望所有單詞都突出顯示,但我在替換HTML內容時出錯。

這就是指令試圖做的事:

1. 該指令應突出一個或多個單詞。例如。 如果搜索條件是「文檔合法」,它應該突出顯示它們,即使它們不是這個順序。

因此,像「法律事項文件」這樣的文本應該同時突出顯示,「合法」和「文件」。

2. 如果單詞少於3個字符不會突出顯示。

3. 如果找不到該單詞,請嘗試從其中刪除最後一個字符,直到其長度小於3.您可以搜索「尺寸」,搜索引擎可以返回包含「尺寸」 「十分錢」。

爲了以防萬一,該應用程序是一個離子應用程序。

這是我的代碼。

角度指令:

angular.module('starter.directives', []) 

.directive('highlightSearchTerms', function($compile) { 
    return { 
    restrict: 'A', 
    scope: true, 
    link: function($scope, element, attrs) { 
     $scope.highlightTerm = function(term) { 
     var html = element.html(); 

     var highlighted = html.replace(new RegExp(term, 'gi'), 
      '<span class="highlightedText">$&</span>'); 

     if (highlighted == null) { 
      return false; 
     } 

     // @see 
     // I think that the problem is here, it works the 
     // first time, but the second time it gets here 
     // the following exception is throwed 
     // "Cannot read property 'replaceChild' of null" 
     element.replaceWith(highlighted); 

     return html != highlighted; 
     }; 

     var searchTerms = $scope.searchTerms; 

     if (searchTerms != undefined && searchTerms.length < 3) { 
     return; 
     } 

     var terms = searchTerms.split(' '); 

     // Try to highlight each term unless the word 
     // is less than 3 characters 
     for (var i = 0; i < terms.length; i++) { 
     var term = terms[i]; 

     // // Try to highlight unless the word is less than 3 chars 
     while (term.length > 2) { 
      // If it got highlighted skip to next term 
      // else remove a character from the term and try again 
      if ($scope.highlightTerm(term)) { 
      break; 
      } 

      term = term.substring(0, term.length - 1); 
     } 
     } 
    } 
    }; 
}); 

你可以看到一些奇怪的事情。像使用$ scope.highlightTerm而不是將highlightTerm var傳遞給指令。我無法得到它的工作。

如何正確更改元素的HTML?

這是使用該指令的模板:

<div ng-include src="tplName" highlight-search-terms></div> 

我願做這樣的事情,但我無法得到它的工作:

<div ng-include src="tplName" highlight-search-terms="something to highlight"></div> 

這裏是一個Plunker: http://plnkr.co/edit/BUDzFaTnxTdKqK5JfH0U?p=preview

+0

把這個放入jsFiddler或plunker可能會有所幫助。也不是自己做的,所以不能肯定地評論,但要小心編輯HTML而不使用angularjs'$ compile'服務。我非常肯定你可以使用jQuery來打破HTML中的任何綁定。 – ste2425

+0

非常感謝您提供的重要建議。而$ compile服務,我會檢查出來。 –

+0

ste2425是正確的你的問題是'var html = element.html();'總是返回相同的值,因爲你在替換之後不重新編譯。普諾夫的解決方案的工作原理,但它使用本機JavaScript繞過角,我不知道我們是否總是想要。 – KenavR

回答

1

我覺得你的代碼工作,但問題是,你正在試圖取代正在使用的指令全div。所以你可以做的只是用element.html(highlighted);代替element.replaceWith(highlighted);,它會起作用。

我願做這樣的事情,但我無法得到它的工作:<div ng-include src="tplName" highlight-search-terms="something to highlight"></div>

你已經有了,只需使用attrs在鏈接功能,像這樣:

var terms = attrs.highlightSearchTerms;,和你會得到你通過的highlight-search-terms="something to highlight"

+0

是的!我知道它應該是這樣的。非常感謝你。 –

1

這應該適合你,使用「編譯」功能:

angular.module('starter.directives', []) 

.directive('highlightSearchTerms', function($compile) { 
    return { 
    restrict: 'A', 
    scope: true, 
    compile: function(elem, attrs) { 
     // your code 
     elem[0].innerHTML = '<span class="highlightedText">$&</span>'; 
     // your code 
    } 
    }; 
}); 

Documentation也可以提供幫助。

1

即使棘手的punov的解決方案的作品,我認爲你不應該觸發多個重新編譯單個「線」。我建議將html存儲在變量中,並在每個術語被替換後重新編譯。

下面是一個工作示例 - 但它需要一些拋光。

http://plnkr.co/edit/3zA54A0F2gmVhCComXAb?p=preview

link: function($scope, element, attrs) { 

    var searchTerms = $scope.searchTerms; 
    var terms = searchTerms.split(' '); 
    $scope.highlightedHTML = element.html(); 

    if (searchTerms !== undefined && searchTerms.length < 3) { 
    return; 
    } 

    $scope.highlightTerm = function(term) { 
    console.log("html - ", term, html); 
    var highlighted = $scope.highlightedHTML.replace(new RegExp(term, 'gi'), 
     '<span class="highlightedText">$&</span>'); 

    //element.replaceWith(highlighted); 

    return highlighted; 
    }; 

    function highlight(terms, compile) { 
    // Try to highlight each term unless the word 
    // is less than 3 characters 
    // if the term is not highlighted remove one character 
    // from it and try again 
    for (var i = 0; i < terms.length; i++) { 
     var term = terms[i]; 

     while (term.length > 2) { 
     var current = $scope.highlightedHTML; 
     $scope.highlightedHTML = $scope.highlightTerm(term); 


     if (current !== $scope.highlightedHTML) { 
      break; 
     } 

     term = term.substring(0, term.length - 1); 
     } 
    } 

    compile(); 
    } 



    highlight(terms, function() { 
    element.replaceWith($scope.highlightedHTML); 
    }); 
}